/**
 * http 请求功能
 * @date 2023/10/8
 */
import type { AxiosInstance, AxiosResponse } from "axios";
import axios from "axios";
import type { HttpInterface } from "@/typings/http";

export class Http {
  // axios 实例
  private instance: AxiosInstance;
  private interceptorHooks?: HttpInterface.InterceptorHooks;
  private readonly showLoading: boolean;

  constructor(config: HttpInterface.ExpandAxiosRequestConfig) {
    // 使用axios.create创建axios实例
    this.instance = axios.create(config);
    this.interceptorHooks = config.interceptorHooks;
    this.showLoading = config.showLoading;
    this.setupInterceptors();
  }

  // 通用拦截，在初始化时就进行注册和运行，对基础属性进行处理
  private setupInterceptors() {
    this.instance.interceptors.request.use(config => {
      //设置loading
      if ((config as HttpInterface.ExpandAxiosRequestConfig).showLoading) {
      } else {
        if (this.showLoading) {
          window.$loadingBar.start();
        }
      }
      return config;
    });

    this.instance.interceptors.response.use(
      // 请求完毕，关闭loading
      res => {
        if (this.showLoading) {
          window.$loadingBar.finish();
        }
        return res;
      },
      err => {
        if (this.showLoading) {
          window.$loadingBar.finish();
        }
        return err;
      },
    );
    this.instance.interceptors.request.use(
      this.interceptorHooks?.requestInterceptor,
      this.interceptorHooks?.requestInterceptorCatch,
    );
    this.instance.interceptors.response.use(
      this.interceptorHooks?.responseInterceptor,
      this.interceptorHooks?.responseInterceptorCatch,
    );
  }

  // 定义核心请求
  public request(config: HttpInterface.ExpandAxiosRequestConfig): Promise<AxiosResponse> {
    // ！！！?? 注意：axios 已经将请求使用 promise 封装过了
    // 这里直接返回，不需要我们再使用 promise 封装一层
    return this.instance.request(config);
  }

  public get<T = any>(
    url: string,
    config?: HttpInterface.ExpandAxiosRequestConfig,
  ): Promise<AxiosResponse<HttpInterface.ApiResponse<T>>> {
    return this.instance.get(url, config);
  }

  public post<T = any>(url: string, data?: any, config?: HttpInterface.ExpandAxiosRequestConfig): Promise<T> {
    return this.instance.post(url, data, config);
  }

  public put<T = any>(url: string, data?: any, config?: HttpInterface.ExpandAxiosRequestConfig): Promise<T> {
    return this.instance.put(url, data, config);
  }

  public delete<T = any>(url: string, config?: HttpInterface.ExpandAxiosRequestConfig): Promise<T> {
    return this.instance.delete(url, config);
  }
}
